package com.feditory.shop.provider.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.feditory.common.condition.PagingCond;
import com.feditory.common.domain.DataHandleStatus;
import com.feditory.common.domain.ShopType;
import com.feditory.shop.domain.FamousWholesaleShop;
import com.feditory.shop.domain.RetailShop;
import com.feditory.shop.domain.WholesaleShop;
import com.feditory.shop.provider.ShopProvider;
import com.feditory.util.CollectionUtils;

public class ShopProviderImpl implements ShopProvider {

    @PersistenceContext
    private EntityManager em;

    @Override
    public long registerWholeShop(WholesaleShop shop) {
        String shopId = this.generateShopId(ShopType.WHOLESALE);

        this.checkShopId(ShopType.WHOLESALE, shopId);

        shop.setShopId(shopId);
        shop.setHandleStatus(DataHandleStatus.getNewDataHandler());
        this.em.persist(shop);
        return shop.getId();
    }

    @Override
    public WholesaleShop retrieveWholesaleShop(String shopId) {
        StringBuilder qlString = new StringBuilder(100);
        qlString.append(" SELECT s  FROM WholesaleShop s ");
        qlString.append("  WHERE s.shopId = :shopId ");
        qlString.append("    AND s.handleStatus.useYn = 1 ");

        Query query = this.em.createQuery(qlString.toString());
        query.setParameter("shopId", shopId);

        List<WholesaleShop> wholesaleShops = CollectionUtils.castList(query.getResultList());
        if (wholesaleShops == null || wholesaleShops.isEmpty()) return null;
        return wholesaleShops.get(0);
    }

    /* (non-Javadoc)
     * @see com.feditory.shop.provider.ShopProvider#retrieveWholesaleShopName(java.util.List)
     */
    @Override
    public Map<String, String> retrieveWholesaleShopName(List<String> wholesaleShopIds) {
        StringBuilder qlString = new StringBuilder(100);
        qlString.append(" SELECT s.shopName,s.shopId  FROM WholesaleShop s ");
        qlString.append("  WHERE s.shopId IN (:shopIds) ");
        qlString.append("    AND s.handleStatus.useYn = 1 ");

        Query query = this.em.createQuery(qlString.toString());
        query.setParameter("shopIds", wholesaleShopIds);

        List<Object[]> queryResults = CollectionUtils.castList(query.getResultList());
        if (queryResults.isEmpty()) return null;

        Map<String, String> shopNameMaps = new HashMap<String, String>();
        for (Object[] objects : queryResults) {
            shopNameMaps.put((String) objects[1], (String) objects[0]);
        }

        return shopNameMaps;
    }

    @Override
    public long registerRetailShop(RetailShop shop) {
        String shopId = this.generateShopId(ShopType.RETAIL);
        this.checkShopId(ShopType.WHOLESALE, shopId);

        shop.setShopId(shopId);
        shop.setHandleStatus(DataHandleStatus.getNewDataHandler());
        this.em.persist(shop);
        return shop.getId();
    }

    private void checkShopId(ShopType shopType, String shopId) {
        StringBuilder qlString = new StringBuilder(100);
        qlString.append(" SELECT s.shopId ");
        if (shopType == ShopType.RETAIL) {
            qlString.append("FROM RetailShop s ");
        }
        else if (shopType == ShopType.WHOLESALE) {
            qlString.append("FROM WholesaleShop s ");
        }
        qlString.append("   WHERE s.shopId = :shopId ");
        Query query = this.em.createQuery(qlString.toString());
        query.setParameter("shopId", shopId);

        if (query.getResultList() != null && query.getResultList().size() > 0) {
            throw new RuntimeException("해당 샵아이디 [" + shopId + "]가 존재합니다. ");
        }
    }

    public String generateShopId(ShopType shopType) {

        StringBuilder qlString = new StringBuilder(100);
        qlString.append(" SELECT MAX(s.id)  ");
        if (shopType == ShopType.RETAIL) {
            qlString.append("FROM RetailShop s ");
        }
        else if (shopType == ShopType.WHOLESALE) {
            qlString.append("FROM WholesaleShop s ");
        }
        //        qlString.append(" WHERE s.shopType = :shopType ");
        Query query = this.em.createQuery(qlString.toString());
        //        query.setParameter("shopType", shopType);
        Long id = (Long) query.getSingleResult();
        if (id == null) id = 0L;
        String shopId = "";
        switch (shopType) {
        case RETAIL:
            shopId = "R" + (id + 1);
            break;
        case WHOLESALE:
            shopId = "W" + (id + 1);
            break;
        default:
            break;
        }
        return shopId;
    }

    // ----------------------------------------------------------------
    // 인기샵 FamousWholesaleShop
    // ----------------------------------------------------------------

    @Override
    public void registerFamousWholesaleShop(FamousWholesaleShop shop) {
        if (this.retrieveWholesaleShop(shop.getWholesaleShopId()) == null) {
            throw new RuntimeException("샵아이디[" + shop.getWholesaleShopId() + "]는 등록되지 않는 샵입니다.");
        }
        this.em.persist(shop);
    }

    /* (non-Javadoc)
     * @see com.feditory.shop.provider.ShopProvider#retrieveFamounWholeSaleShops(int, int)
     */
    @Override
    public List<FamousWholesaleShop> retrieveFamounWholeSaleShops(PagingCond pagingCond) {
        StringBuilder qlString = new StringBuilder(100);
        qlString.append("   SELECT fws  ");
        qlString.append("     FROM FamousWholesaleShop fws ");
        qlString.append(" ORDER BY fws.ranking ");
        Query query = this.em.createQuery(qlString.toString());
        query.setFirstResult(pagingCond.getFirst());
        query.setMaxResults(pagingCond.getLast());

        return CollectionUtils.castList(query.getResultList());
    }
}
